package cqrtplm.aop;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.github.pagehelper.PageInfo;
import com.hustcad.plm.pdm.container.model.dto.search.ContainerEntityParamDTO;
import com.hustcad.plm.pdm.container.model.vo.search.ContainerEntityVO;
import com.hustcad.plm.pdm.container.service.TyplmPdmContainerService;
import com.hustcad.plm.pdm.folder.model.dto.SubfolderDTO;
import com.hustcad.plm.pdm.folder.model.vo.SubfolderVO;
import com.hustcad.plm.pdm.folder.model.vo.SubfolderWebVO;
import com.hustcad.plm.pdm.folder.service.TyplmSubFolderLinkService;
import com.hustcad.plm.pdm.type.model.vo.OOTBTypeVO;
import com.hustcad.plm.pdm.type.model.vo.TypeVO;
import com.hustcad.plm.pdm.user.service.TyplmUserService;
import com.ty.basic.constant.ContainerConstant;
import com.ty.basic.constant.TableTypeConstrant;
import com.ty.basic.entity.IdentifierEntity;
import com.ty.basic.entity.folder.SubfolderDO;
import com.ty.basic.entity.org.UserDO;
import com.ty.basic.handler.exceptionhandler.exception.ResponseCodeEnum;
import com.ty.basic.handler.exceptionhandler.exception.TyException;
import com.ty.basic.response.ResponseResult;
import com.ty.basic.session.TyAccountContext;
import com.ty.security.util.TyCommonUtils;
import cqrtplm.constant.RTErrorCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author fxw
 * @version 1.0
 * @className RTCreateTypeAOP
 * @description 创建类型切面
 * @since 2025/11/4 18:56
 */
@Aspect
@Component
@Slf4j
public class RTCreateTypeAOP {
    // 添加本地缓存路径
    private final Map<String, String> folderPathCache = new ConcurrentHashMap<>();
    @Resource
    private TyplmSubFolderLinkService typlmSubFolderLinkService;
    @Resource
    private TyplmPdmContainerService typlmPdmContainerService;
    @Resource
    private TyplmUserService typlmUserService;

    @Around("execution(* com.hustcad.plm.pdm.type.service.impl.TyplmTypeServiceImpl.createOOTBType(..))")
    @Transactional
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        Object arg = joinPoint.getArgs()[0];
        // 参数校验
        if (!(arg instanceof JSONObject || arg instanceof Map)) {
            log.warn("Invalid argument type for createOOTBType: {}", arg.getClass().getName());
            return joinPoint.proceed();
        }
        JSONObject jsonObject = null;
        if (arg instanceof JSONObject) {
            JSONObject objectParam = (JSONObject) arg;
            jsonObject = TyCommonUtils.requireNonNull(objectParam.getJSONObject("params"), "params");
        } else {
            Map<?, ?> mapParam = (Map<?, ?>) arg;
            Object paramsObj = mapParam.get("params");
            if (paramsObj instanceof Map) {
                jsonObject = new JSONObject((Map<String, Object>) paramsObj);
            } else {
                throw new IllegalArgumentException("params字段不是有效的Map类型");
            }
        }
        if (jsonObject != null) {
            //是否创建文件夹校验
            boolean skipFolderValidation = !ObjectUtils.isNull(
                    jsonObject.getBoolean("skipFolderValidation")) && jsonObject.getBoolean("skipFolderValidation");
            // 处理JSONObject类型参数
            OOTBTypeVO vo = JSON.parseObject(jsonObject.getJSONObject("entity").toJSONString(), OOTBTypeVO.class);
            String description = vo.getDescription();
            // 判断是否为OOTB类型
            TypeVO relentity = null;
            if (Objects.nonNull(jsonObject.getJSONObject("relentity"))) {
                relentity = JSON.parseObject(jsonObject.getJSONObject("relentity").toJSONString(), TypeVO.class);
            }

            if (ObjectUtils.isEmpty(relentity)) {
                TyException.throwSingleTyExceptionVarargs(ResponseCodeEnum.OBJECT_STATE_CHECK_NOT_PASS,
                                                          "传递数据异常！！");
            }
            // 判断是否为非OOTB类型
            List<String> includedTypes = Arrays.asList(TableTypeConstrant.TY_DOC_OTYPE,
                                                       TableTypeConstrant.TY_CADDOC_OTYPE,
                                                       TableTypeConstrant.TY_PART_OTYPE,
                                                       TableTypeConstrant.TY_FORMDATA_TYPE);
            List<String> tempInthid = new ArrayList<>(Collections.singletonList(relentity.getInthid()));
            tempInthid.retainAll(includedTypes);
            if (tempInthid.isEmpty()) {
                return joinPoint.proceed();
            }



            if (ObjectUtils.isNotEmpty(description)) {
                UserDO user = this.typlmUserService.queryUserByName("admin");
                if (Objects.nonNull(user)) {
                    TyAccountContext.setUser(user);
                }
                //获取所有产品库
                ContainerEntityParamDTO containerEntityParamDTO = new ContainerEntityParamDTO();
                containerEntityParamDTO.setOtype(TableTypeConstrant.TY_PDMLINKPRODUCT_OTYPE);
                containerEntityParamDTO.setPageNum(1);
                containerEntityParamDTO.setPageSize(999999999);
                containerEntityParamDTO.setNeedIBA(false);
                //获取存储库
                PageInfo<ContainerEntityVO> containerEntityProductLibrary = typlmPdmContainerService.queryContainerListMyself(
                        containerEntityParamDTO);
                ContainerEntityParamDTO containerEntityParamDTO1 = new ContainerEntityParamDTO();
                containerEntityParamDTO1.setNeedIBA(true);
                containerEntityParamDTO1.setOtype(TableTypeConstrant.TY_LIBRARY_OTYPE);
                containerEntityParamDTO1.setOperation("");
                containerEntityParamDTO1.setName("");
                containerEntityParamDTO1.setIdentifierRef(
                        new IdentifierEntity(null, TableTypeConstrant.TY_LIBRARY_OTYPE));
                PageInfo<ContainerEntityVO> containerEntityMemoryCard = typlmPdmContainerService.queryContainerListMyself(
                        containerEntityParamDTO1);
                String[] split = description.split("/");
                List<ContainerEntityVO> voList = containerEntityProductLibrary.getList().stream().filter(
                        containerEntityVO -> {
                            return containerEntityVO.getName().equals(split[0]);
                        }).collect(Collectors.toList());
                List<ContainerEntityVO> voList2 = containerEntityMemoryCard.getList().stream().filter(
                        containerEntityVO -> {
                            return containerEntityVO.getName().equals(split[0]);
                        }).collect(Collectors.toList());
                // 检查是否有匹配的容器
                if (voList.isEmpty() && voList2.isEmpty()) {
                    throw RTErrorCodeEnum.DOC_TYPE_ERROR.getException("产品库或存储库中(" + split[0] + ")不存在");
                }
                boolean returnResult = false;
                if (!voList.isEmpty()) {
                    returnResult = judgeToGenerate(split, "产品库", voList, skipFolderValidation);
                }
                if (!voList2.isEmpty()) {
                    returnResult = judgeToGenerate(split, "存储库", voList2, skipFolderValidation);
                }
                if (returnResult) {
                    throw new FolderValidationException("文件不曾存在是否创建", jsonObject);
                }
            }
        }
        return joinPoint.proceed();
    }

    /**
     * @param split
     * @param normalContainerType
     * @param voList
     * @param skipFolderValidation
     * @return boolean
     * @author fxw
     * @description 判断是否生成文件夹
     * @since 2025/11/13 15:26
     */
    private boolean judgeToGenerate(String[] split, String normalContainerType, List<ContainerEntityVO> voList,
                                    boolean skipFolderValidation) {
        boolean b = false;
        for (ContainerEntityVO containerEntityVO : voList) {
            StringBuilder sb = new StringBuilder();
            //兼容系统路径
            sb.append("/").append(split.length > 0 ? split[0] : "");
            SubfolderDTO subfolderWebVO = new SubfolderDTO();
            subfolderWebVO.setOtype(containerEntityVO.getOtype());
            subfolderWebVO.setOid(containerEntityVO.getOid());
            List<SubfolderWebVO> subfolderByProductId = typlmSubFolderLinkService.getSubfolderByProductId(
                    containerEntityVO.getOid());
            if (split.length > 1) {
                for (int i = 1; i < split.length; i++) {
                    sb.append("/").append(split[i]);
                    //检验文件夹路径是否存在
                    b = collectAllFolderPaths(subfolderByProductId, sb.toString(), skipFolderValidation);
                    if (!b || skipFolderValidation) {
                        //返回前端的参数
                        if (!skipFolderValidation) {
                            return true;
                        }

                        SubfolderVO subfolderDTO = new SubfolderVO();
                        if (i - 1 == 0) {
                            subfolderDTO.setParentOid(String.valueOf(containerEntityVO.getDefaultcabinetoid()));
                            subfolderDTO.setParentOtype(TableTypeConstrant.TY_CABINET_OTYPE);
                        } else {
                            String s = "存储库".equals(normalContainerType) ? ContainerConstant.getNormalContainerType()
                                    .get(1) : ContainerConstant.getNormalContainerType().get(0);
                            // 判空保护和服务查询结果有效性验证
                            SubfolderDO subfolderDO = typlmSubFolderLinkService
                                    .querySubFolderByFullPath(s, split[0],
                                                              "/" + String.join("/", Arrays.copyOfRange(split,
                                                                     1, Math.max(1,split.length - 1))));
                            if (subfolderDO != null) {
                                subfolderDTO.setParentOid(String.valueOf(subfolderDO.getOid()));
                            } else {
                                // 根据业务需求决定是否抛异常或设置默认值
                                subfolderDTO.setParentOid(null);
                            }
                            subfolderDTO.setParentOtype(TableTypeConstrant.TY_SUBFOLDER_OTYPE);
                        }
                        subfolderDTO.setOtype(TableTypeConstrant.TY_SUBFOLDER_OTYPE);
                        subfolderDTO.setName(split[i]);
                        subfolderDTO.setDescription("--系统自动创建--文件夹--");
                        typlmSubFolderLinkService.createSubfolder(subfolderDTO);
                    }
                }
            } else {
                TyException.throwSingleTyExceptionVarargs(ResponseCodeEnum.BIZ_FOLDER_PATH_FORMAT_INCORRECT,
                                                          String.join("/", split));
            }
        }
        return false;
    }

    /**
     * @param folders
     * @param path
     * @param skipFolderValidation
     * @return boolean
     * @author fxw
     * @description 递归查询文件夹路径
     * @since 2025/11/13 15:26
     */
    private boolean collectAllFolderPaths(List<SubfolderWebVO> folders, String path, boolean skipFolderValidation) {
        boolean isPathFound = false;
        for (SubfolderWebVO folder : folders) {
            if (folder == null) {
                continue;
            }
            try {
                //直接返回更新避免数据库操作
                if (skipFolderValidation) {
                    break;
                }
                if (Objects.equals(folderPathCache.get(folder.getOid()), path)) {
                    //缓存命中直接返回
                    isPathFound = true;
                    break;
                }
                // 收集当前文件夹信息
                String currentPath = typlmSubFolderLinkService.recursiveQueryFolderPath(folder.getOid(), true);
                if (currentPath != null && currentPath.equals(path)) {
                    isPathFound = true;
                    break;
                }
                //本地缓存
                folderPathCache.put(folder.getOid(), currentPath);
                // 判断是否有子节点并进一步搜索
                if (Boolean.parseBoolean(folder.getHasChildren())) {
                    List<SubfolderWebVO> children = typlmSubFolderLinkService.querySubfolderByParent(
                            Convert.toBigInteger(folder.getOid()), folder.getOtype());
                    if (children != null && !children.isEmpty()) {
                        boolean childResult = collectAllFolderPaths(children, path, false);
                        if (childResult) {
                            isPathFound = true;
                            break; // 找到后提前退出循环
                        }
                    }
                }
            } catch (Exception e) {
                // 记录异常但不影响整体流程
                System.err.println("Error processing folder: " + folder.getOid() + ", message: " + e.getMessage());
            }
        }
        return isPathFound;
    }

    @RestControllerAdvice
    static public class GlobalExceptionHandler {
        @ExceptionHandler(FolderValidationException.class)
        public ResponseResult handleFolderValidation(FolderValidationException e) {
            return ResponseResult.success().setData(e.getData());
        }
    }

    //异常类用于自定义前端数据
    public static class FolderValidationException extends RuntimeException {
        private final JSONObject data;

        public FolderValidationException(String message, JSONObject data) {
            super(message);
            this.data = data;
        }

        public JSONObject getData() {
            return data;
        }
    }
}

